package com.example.rdb.conf.etcd;

import com.example.rdb.conf.ConfigInfo;
import com.example.rdb.conf.Constants;
import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
import io.etcd.jetcd.kv.DeleteResponse;
import io.etcd.jetcd.kv.GetResponse;
import io.etcd.jetcd.options.DeleteOption;
import io.etcd.jetcd.options.GetOption;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.*;

/**
 * etcd 操作工具，包括启动监听和操作etcd v3 版本协议，只测试功能
 *
 * @author xyc
 * @version 1.0
 */
@Slf4j
public class WriteEtcdUtil {

	private static final Charset UTF_8 = StandardCharsets.UTF_8;
	// etcd客户端链接
	private static Client etcdClient = null;

	private static final Integer corePoolSize = 0;
	private static final Integer maximumPoolSize = Integer.MAX_VALUE;
	private static final Long keepAliveTime = 60L;


	// 链接初始化
	public static synchronized Client getEtclClient() {
		if (etcdClient == null) {
			String urlInfo = ConfigInfo.etcdWrite ;
			System.out.println("urlInfo:"+urlInfo);
//			EtcdConfig config = SpringContextHolder.getBean(EtcdConfig.class);
//			String[] urls = StrUtil.splitToArray(config.getUrls(), StrUtil.C_COMMA);
			String[] urls = urlInfo.split(",");
			ThreadPoolExecutor pool = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,
					keepAliveTime, TimeUnit.SECONDS, new SynchronousQueue<>());
			// ByteSequence user = ByteSequence.from(config.getUserName(), StandardCharsets.UTF_8);
			// ByteSequence password = ByteSequence.from(config.getPassword().getBytes(StandardCharsets.UTF_8));
			etcdClient = Client.builder()
					.endpoints(urls)
					// .user(user)
					// .password(password)
					.executorService(pool)
					.build();
		}
		return etcdClient;
	}

	/**
	 * 新增或者修改指定的配置
	 *
	 * @param key 键
	 * @param value 值
	 * @author xyc
	 */
	public static void putEtcdValueByKey(String key, String value) throws Exception {
		Client client = WriteEtcdUtil.getEtclClient();

		client.getKVClient().put(ByteSequence.from(key, UTF_8), ByteSequence.from(value, UTF_8)).get();
	}

	/**
	 * 查询指定的key名称对应的value
	 *
	 * @param key 键
	 * @return value值
	 * @author xyc
	 */
	public static String getEtcdValueByKey(String key) throws Exception {
		synchronized (WriteEtcdUtil.class) {
			Client client = WriteEtcdUtil.getEtclClient();
			GetResponse getResponse = client.getKVClient()
					.get(ByteSequence.from(key, UTF_8), GetOption.newBuilder().build()).get();

			if (getResponse.getKvs().isEmpty()) {
				return null;
			}

			return getResponse.getKvs().get(0).getValue().toString(UTF_8);
		}
	}

	/**
	 * 根据key的前缀批量查询
	 *
	 * @param key 键
	 */
	public static Map<String, String> getEtcdValueList(String key) throws Exception {
		synchronized (WriteEtcdUtil.class) {
			TreeMap<String, String> map = new TreeMap<>();
			Client client = WriteEtcdUtil.getEtclClient();
			// 设置Key
			ByteSequence sequenceKey = ByteSequence.from(key.getBytes(StandardCharsets.UTF_8));
			// 构建GetOption对象，通过withPrefix方法，设置前缀匹配的key
			GetOption op = GetOption.newBuilder().withPrefix(sequenceKey).build();
			// 通过KV client的get方法查询，跟普通的get请求的区别就是多了一个GetOption参数
			CompletableFuture<GetResponse> getFuture = client.getKVClient().get(sequenceKey, op);
			// 获取get请求的结果
			GetResponse response = getFuture.get();
			// 通过getKvs可以查询get请求返回的结果，可能存在多个Key的情况，所以需要遍历
			response.getKvs().forEach(obj -> {
				// 查询到的key/value也是字节类型，需要转换，这里转换成字符串。
				map.put(obj.getKey().toString(UTF_8), obj.getValue().toString(UTF_8));
			});

			return map;
		}
	}


	/**
	 * 删除指定的配置
	 *
	 * @param key 键
	 * @author xyc
	 */
	public static void deleteEtcdValueByKey(String key) throws InterruptedException, ExecutionException {
		Client client = WriteEtcdUtil.getEtclClient();
		client.getKVClient().delete(ByteSequence.from(key, UTF_8)).get();
	}

    /**
	 * 根据前缀批量删除数据
	 *
	 * @param key 键
	 * @author xyc
	 */
	public static void deleteEtcdValueListByKey(String key) {
		synchronized (WriteEtcdUtil.class) {
			TreeMap<String, String> map = new TreeMap<>();
			Client client = WriteEtcdUtil.getEtclClient();
			// 设置Key
			ByteSequence sequenceKey = ByteSequence.from(key.getBytes(StandardCharsets.UTF_8));
			// 构建GetOption对象，通过withPrefix方法，设置前缀匹配的key
			DeleteOption op = DeleteOption.newBuilder().withPrefix(sequenceKey).build();
			// 通过KV client的delete方法批量删除
			CompletableFuture<DeleteResponse> getFuture = client.getKVClient().delete(sequenceKey, op);
		}
	}

}
